﻿using LSFTP.MultithreadFileDownload;
using Renci.SshNet;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;

namespace LSFTP.MultithreadFileUpload
{
    public class UpLoadFile
    {
        public delegate void dlgSendMsg(UpMsg msg);
        public event dlgSendMsg doSendMsg;

        public int ThreadNum = 3;
        List<Thread> list = new List<Thread>();

        public UpLoadFile()
        {
            doSendMsg += Change;
        }

        private void Change(UpMsg msg)
        {
            if(msg.Tag == UpStatus.Error || msg.Tag == UpStatus.End)
            {
                StartUp(1);
            }
        }

        public void AddUp(string remoteFile,string localFile,SFTPClient sftp,int Id)
        {
            Thread tsk = new Thread(() =>
            {
                upload(remoteFile, localFile, sftp, Id);
            });
            list.Add(tsk);
        }

        public void StartUp(int StartNum = 3)
        {
            for(int i2 = 0; i2 < StartNum; i2++)
            {
                lock(list)
                {
                    for(int i = 0;i< list.Count;i++)
                    {
                        if (list[i].ThreadState == ThreadState.Unstarted || list[i].ThreadState == ThreadState.Suspended)
                        {
                            list[i].Start();
                            break;
                        }
                    }
                }
            }
        }

        private void upload(string remotePath,string localFile,SFTPClient client, int id = 0)
        {
            UpMsg upMsg = new UpMsg();
            try
            {
                upMsg.Id = id;
                upMsg.Tag = UpStatus.Start;
                doSendMsg(upMsg);

                SftpClient sftp = client.GetSftp();

                FileInfo fileInfo = new FileInfo(localFile);
                upMsg.Tag = UpStatus.GetLength;
                upMsg.Length = (ulong)fileInfo.Length;
                doSendMsg(upMsg);

                DateTime start = DateTime.Now;
                TimeSpan ts;
                using (var fileStream = new FileStream(localFile, FileMode.Open))
                {

                    string serverPath = remotePath.Replace(@"\", "/");
                    if (!sftp.Exists(serverPath))
                        sftp.CreateDirectory(serverPath);


                    if (upMsg.Length == 0)
                    {
                        upMsg.Size = 0; //下载总量
                        upMsg.Tag = UpStatus.End;
                        upMsg.SpeedInfo = "0 K";
                        upMsg.SurplusInfo = "已完成";
                        doSendMsg(upMsg);

                        sftp.UploadFile(fileStream, serverPath.TrimEnd('/') + "/" + fileInfo.Name, true, (size) => { });
                        return;
                    }




                    sftp.BufferSize = 4 * 1024;
                    sftp.UploadFile(fileStream, serverPath.TrimEnd('/') + "/" + fileInfo.Name, true, (size) =>
                    {
                        if (size != upMsg.Length)
                        {
                            ts = DateTime.Now - start;
                            if (ts.TotalMilliseconds < 250) return;
                            start = DateTime.Now;
                        }

                        //下载速度
                        if (upMsg.Size == 0)
                        {
                            upMsg.Speed = size;
                        }
                        else
                        {
                            upMsg.Speed = (float)(size - upMsg.Size) * 4;

                        }
                        if (upMsg.Speed == 0)
                        {
                            upMsg.Surplus = -1;
                            upMsg.SurplusInfo = "未知";
                        }
                        else
                        {
                            upMsg.Surplus = ((upMsg.Length - upMsg.Size) / upMsg.Speed);
                        }
                        upMsg.Size = size; //下载总量

                        if (size == upMsg.Length)
                        {
                            //下载完成
                            upMsg.Tag = UpStatus.End;
                            upMsg.SpeedInfo = "0 K";
                            upMsg.SurplusInfo = "已完成";
                        }
                        else
                        {
                            //下载中
                            upMsg.Tag = UpStatus.UpLoad;
                        }



                        if (doSendMsg != null) doSendMsg(upMsg);//通知具体调用者下载进度
                    });
                }
            }
            catch(Exception e)
            {
                upMsg.Id = id;
                upMsg.Length = 0;
                upMsg.Tag = UpStatus.Error;
                upMsg.ErrMessage = e.Message;
                doSendMsg(upMsg);
            }
        }

        public void StopUp()
        {
            lock (list)
            {
                try
                {
                    for(int i = 0; i < list.Count; i++)
                    {
                        list[i].Abort(3000);
                    }
                    list.Clear();
                }
                catch (Exception)
                {

                }
            }
        }
    }
}
